import { createSkeleton } from "utils/util";
import { MoveRocker, AttackRocker, SkillRocker } from "../Rocker";
import socket from "ctrl/socket";
import Map from "battle/components/Map";

let loadedAssets = [];

const { Tween, Handler } = Laya;

export default class BaseRole extends Laya.Sprite {

    constructor(data) {
        super();
        Object.assign(this, data);
        this.x = data.x;
        this.y = data.y;
        this.initData(data);
    }

    initData(data) {
        let body = this.body = createSkeleton(`assets/role/${ this.ho }/game/skin_1`);
        body.scale(0.5, 0.5);
        body.zOrder = 1;
        body.play("standby", true);
        this.addChild(body);
        this.direct = [0, 0];
        this.isMyRole = (data.uid==GM.user_id);
        this.indicator = new Laya.Sprite();
        this.addChild(this.indicator);

        this.statusBar = new ui.Room.Com.RoleStatusBarUI();
        this.statusBar.x = -50;
        this.statusBar.top = -160;
        this.addChild(this.statusBar);

        if (this.isMyRole) this.initOperator();

    }

    initOperator() {
        MoveRocker.getInstance().on("ROKER_MOVE", this, (direct, speed, angle)=> {
            direct = direct.map(v=> v*2);
            this.startMove(direct);
        });

        MoveRocker.getInstance().on("ROKER_EXECUTE", this, (direct, speed, angle)=> {
            this.stop();
        });

        AttackRocker.getInstance().on("ROKER_MOVE", this, (direct, speed, angle)=> {
            this.updateSightLine(direct);
        });

        AttackRocker.getInstance().on("ROKER_EXECUTE", this, (direct)=> {
            this.indicator.graphics.clear();
            let angle = Math.atan2(direct[1], direct[1]) * 180 / Math.PI;
            (angle<0) && (angle+=360);
            Sail.io.emit("fire", { a: angle, roomNo: this.manger.roomNo });
            this.attack();
        });

        SkillRocker.getInstance().on("ROKER_EXECUTE", this, (direct)=> {
            let angle = Math.atan2(direct[1], direct[1]) * 180 / Math.PI;
            (angle<0) && (angle+=360);
            Sail.io.emit("clutchshot", { a: angle, roomNo: this.manger.roomNo });
        });

        this.on("SKILL_POWER", this, (data)=> {
            let skillRocker = SkillRocker.getInstance();
            skillRocker.setPower();
        });
    }


    startMove(direct) {
        if (!(Math.abs(direct[0])>0.01 || Math.abs(direct[1])>0.01)) return this.stop();
        this.walkStatus = 1;
        this.direct = direct;
        this._moveLoopNum = 0;
        Laya.timer.clear(this, this._move);
        Laya.timer.frameLoop(1, this, this._move);
    }

    _move() {
        this.x += this.direct[0];
        this.y += this.direct[1];
        this.direct[0]!==0 && (this.faceDirect = this.direct[0]<0? -1 : 1);
        Map.getInstance().setFocus(this.x, this.y);
        if (this.isMyRole) this.shouldSyncToServe();
    }

    syncFromServer() {
        this.lastOtherSyncTime = Date.now();
        if (!this.syncServered) {
            this.syncServered = true;
            Laya.timer.clear(this, this._move2);
            Laya.timer.frameLoop(1, this, this._move2);
        }
        let { x, y, mx, my } = this.syncData;
        mx!=0 && ( this.faceDirect = mx<0 ? -1: 1 );
    }

    checkFromServer() {
        let { x, y, mx, my } = this.syncData;
        if (Math.abs(this.x-x) > Math.abs(mx)*2) this.x = x;
        if (Math.abs(this.y-y) > Math.abs(my)*2) this.y = y;
        // Map.getInstance().setFocus(this.x, this.y);
    }

    _move2() {
        let { x, y, mx, my, uid } = this.syncData;
        const divide = 0.48; //(32ms fps/66ms interval) 
        let lostime = Date.now() - this.lastOtherSyncTime - 66;
        if (lostime>0) {
            x = x + (mx * lostime) / 33;
            y = y + (my * lostime) / 33;
        }
        let diffX = parseInt(x - this.x), diffY = parseInt(y - this.y);
        let directX = diffX * divide;
        let directY = diffY * divide;

        let moved = false;
        if (Math.abs(this.x-x)>=1 || Math.abs(this.y-y)>=1) {
            let _directX, _directY;
            moved = (Math.abs(this.x-x)>=1 || Math.abs(this.y-y)>=1);
            this.x += directX;
            this.y += directY;
        } else {
            this.x = x;
            this.y = y;
        }
        this.walkStatus = moved? 1: 0;
    }


    shouldSyncToServe() {
        let now = Date.now();
        if (now-this.lastSyncTime >= 33) {
            this.lastSyncTime = now;
            let x = parseInt(this.x), y = parseInt(this.y);
            socket.send("go", { x: x, y: y, mx: this.direct[0], my: this.direct[1], uid: this.uid });
        }
    }

    stop() {
        this._moveLoopNum = 0;
        this.walkStatus = 0;
        this.direct = [0, 0];
        Laya.timer.clear(this, this._move);
        if (this.isMyRole) {
            socket.send("stop", { x: parseInt(this.x), y: parseInt(this.y), mx: this.direct[0], my: this.direct[1], uid: this.uid });
        }
    }

    set faceDirect(val) {
        this._faceDirect = val;
        this.body.scaleX = 0.5 * val;
    }

    get faceDirect() {
        return this._faceDirect;
    }

    set walkStatus(val) {
        if (this._walkStatus === val) return;
        this._walkStatus = val;
        switch(val) {
            case 0:
                this.body.play("standby", true);
                break;
            case 1:
                this.body.play("walk", true);
                break;
        }
    }

    get walkStatus() {
        return this._walkStatus;
    }

    
    putInMap() {
        Map.getInstance().addChild(this);
        this.lastSyncTime = Date.now();
    }

    die() {
        if (false) this.manger.destoryRole(this);
    }

    updateSightLine(direct) {
        console.warn("方法未定义");
    }
    
    /**
     * @abstract
     */
    attack() {
        console.warn("方法未定义");
    }

    useSkill() {
        console.warn("方法未定义");
    }

    takeEffect() {
        console.warn("方法未定义");
    }



}